<script setup>
import { useRoute, useRouter } from 'vue-router'
import api from '@/api'
import { ref, onMounted, nextTick } from 'vue'
import Player from 'xgplayer'
import HlsJsPlugin from 'xgplayer-hls.js'
import { transformDuration } from '@/utils'
import { Swiper, SwiperSlide } from 'swiper/vue'
import 'swiper/css'

const $route = useRoute()
const $router = useRouter()
const course = ref()
const sections = ref([])
const swipeItems = ref([0, 0, 0])
const players = {}
const currentSliderIndex = ref(0)
const currentVideoIndex = ref(0)
const popupHeight = ref('0')
const tabActive = ref('')
const ranks = ref([])
const popupLoading = ref(false)
const watch = ref(null)
const watchSectionIndex = ref(null)
const catelogVisible = ref(false)

const togglePopup = (tab) => {
  if (tab == tabActive.value) {
    popupHeight.value = '0'
    tabActive.value = ''
  } else {
    tabActive.value = tab
    popupHeight.value = '60%'

    if (tab == 'ranks') {
      getCourseRanks()
    }
  }
}

const getCourseRanks = async () => {
  popupLoading.value = true

  try {
    ranks.value = await api.get(`courses/${$route.params.id}/ranks`)
  } catch (error) {
    console.error(error)
  }

  popupLoading.value = false
}

const getCourse = async () => {
  const res = await api.get(`courses/${$route.params.id}`)
  course.value = res.data
  sections.value = course.value.sections
}

const onSlideChange = (swiper) => {
  const prevIndex = swiper.realIndex == 0 ? 2 : swiper.realIndex - 1
  const nextIndex = swiper.realIndex == 2 ? 0 : swiper.realIndex + 1

  currentSliderIndex.value = swiper.realIndex
  currentVideoIndex.value = swipeItems.value[swiper.realIndex]

  // 下滑
  if (swiper.swipeDirection == 'next') {
    players[prevIndex].pause()
    players[swiper.realIndex].play()

    // 更新下个视频
    swipeItems.value[nextIndex] = currentVideoIndex.value == sections.value.length - 1 ? 0 : currentVideoIndex.value + 1
    players[nextIndex].src = sections.value[swipeItems.value[nextIndex]].video_url

    // 上滑
  } else {
    players[nextIndex].pause()
    players[swiper.realIndex].play()

    // 更新上个视频
    swipeItems.value[prevIndex] = currentVideoIndex.value == 0 ? sections.value.length - 1 : currentVideoIndex.value - 1
    players[prevIndex].src = sections.value[swipeItems.value[prevIndex]].video_url
  }
}

const switchCourse = (videoIndex) => {
  catelogVisible.value = false
  currentVideoIndex.value = videoIndex

  //   更新当前视频
  swipeItems.value[currentSliderIndex.value] = videoIndex
  players[currentSliderIndex.value].src = sections.value[swipeItems.value[currentSliderIndex.value]].video_url
  players[currentSliderIndex.value].play()

  // 更新下个视频
  const nextIndex = currentSliderIndex.value == 2 ? 0 : currentSliderIndex.value + 1
  swipeItems.value[nextIndex] = currentVideoIndex.value == sections.value.length - 1 ? 0 : currentVideoIndex.value + 1
  players[nextIndex].src = sections.value[swipeItems.value[nextIndex]].video_url

  // 更新上个视频
  const prevIndex = currentSliderIndex.value == 0 ? 2 : currentSliderIndex.value - 1
  swipeItems.value[prevIndex] = currentVideoIndex.value == 0 ? sections.value.length - 1 : currentVideoIndex.value - 1
  players[prevIndex].src = sections.value[swipeItems.value[prevIndex]].video_url
}

const clickVideo = (index) => {
  const player = players[`${index}`]
  if (player.paused) {
    player.play()
  } else {
    player.pause()
  }
}

const back = () => {
  if (popupHeight.value == '60%') {
    popupHeight.value = '0'
    tabActive.value = ''
  } else {
    $router.replace($route.query.from || '/')
  }
}

onMounted(async () => {
  await getCourse()

  for (let i = 0; i < swipeItems.value.length; i++) {
    const index = i == 2 ? sections.value.length - 1 : i

    swipeItems.value[i] = index

    let section = null
    if (!isNaN(index)) {
      section = sections.value[index]
    }

    nextTick(() => {
      players[`${i}`] = new Player({
        width: '100%',
        height: '100%',
        id: `video-${i}`,
        url: section ? section.video_url : '',
        poster: section ? section.image_url : '',
        // plugins: [HlsJsPlugin],
        controlPlugins: [],
        hlsJsPlugin: {},
        useHls: true,
        ignores: ['replay', 'volume', 'fullscreen'],
        autoplay: false, // 自动播放
        cssFullscreen: false,
        playbackRate: [], // 关闭倍速播放
        playsinline: true,
        'x5-video-player-type': 'h5',
        'x5-video-player-fullscreen': false,
        'x5-video-orientation': 'portraint',
      })

      // 开始观看
      players[`${i}`].on('play', async () => {
        if (watchSectionIndex.value == currentVideoIndex.value) {
          return
        }
        watchSectionIndex.value = currentVideoIndex.value
        watch.value = await api.post(`courses/${sections.value[watchSectionIndex.value].id}/play`)
      })

      // 观看完毕
      players[`${i}`].on('ended', () => {
        if (watch.value && watch.value.id) {
          try {
            api.post(`courses/finished`, { id: watch.value.id })
          } catch (error) {
            console.error(error)
          }
        }
        watch.value = null
        watchSectionIndex.value = null
      })
    })
  }
})
</script>
<template>
  <div class="main">
    <swiper direction="vertical" loop @slideChangeTransitionEnd="onSlideChange">
      <swiper-slide v-for="(index, i) in swipeItems" :key="i">
        <div class="btn btn-back" @click.stop="back()">
          <van-icon name="cross" />
        </div>
        <div :id="`video-${i}`" class="video" @click="clickVideo(i)">
          <template v-if="sections[index]">
            <div class="title">{{ sections[index].order }}. {{ sections[index].name }}</div>
          </template>
        </div>

        <div class="actions">
          <div class="action-item" :class="{ active: tabActive == 'ranks' }" @click="togglePopup('ranks')">学习排行</div>
          <div class="action-item" :class="{ active: tabActive == 'sections' }" @click="togglePopup('sections')">课程目录({{ sections.length }})</div>
          <div class="action-item" style="padding: 5px" :class="{ active: tabActive == 'catelog' }" @click="catelogVisible = true">
            <van-icon name="list-switch" />
          </div>
        </div>
      </swiper-slide>
    </swiper>

    <div class="popup" :style="{ height: popupHeight }">
      <div class="sections" v-show="tabActive == 'sections'">
        <div class="section" :class="{ active: currentVideoIndex == index }" v-for="(section, index) in sections" @click="switchCourse(index)" :key="index">
          <img :src="section.image_url" />

          <div class="section-title">{{ index + 1 }}. {{ section.name }}</div>
          <div class="section-duration">{{ transformDuration(section.duration) }}</div>
        </div>
      </div>

      <van-loading v-if="popupLoading" class="loading" type="spinner" />

      <div class="ranks">
        <table v-if="ranks.length > 0" v-show="tabActive == 'ranks'" cellpadding="0" cellspacing="0">
          <thead>
            <tr style="position: sticky; top: 0">
              <th widh="20%">排名</th>
              <th width="50%">姓名</th>
              <th width="30%">观看进度</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="(item, index) in ranks" :key="index">
              <td>{{ index + 1 }}</td>
              <td>{{ item.name }}</td>
              <td>{{ item.progress }}%</td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>

    <van-popup position="left" class="catelog-popup" v-model:show="catelogVisible" closeable>
      <div style="font-weight: bold; font-size: 16px; margin-top: 6px">课程目录</div>
      <div class="catelog">
        <div class="courses">
          <div class="course" :class="{ active: currentVideoIndex == index }" v-for="(item, index) in sections" :key="item.id" @click="switchCourse(index)">
            {{ index + 1 }}. {{ item.name }}
            <span class="duration">{{ transformDuration(item.duration) }}</span>
          </div>
        </div>
      </div>
    </van-popup>
  </div>
</template>

<style lang="scss" scoped>
.ranks {
  position: relative;
  table {
    border-collapse: collapse;
    border-spacing: 0;
    width: 100%;
    table-layout: fixed;
    th {
      font-weight: 700;
      background: #f6f8fb;
      position: relative;

      &::before {
        content: '';
        display: block;
        width: 100%;
        height: 1px;
        bottom: 0;
        left: 0;
        background: #e5e6eb;
        position: absolute;
      }
    }
    th,
    td {
      font-size: 3.6vw;
      padding: 2vw 1vw;
      text-align: center;
      border-bottom: 1px solid #e5e6eb;
    }
  }
}
.popup {
  flex-shrink: 0;
  transition: height 0.3s;
  background: #fff;
  overflow-y: auto;
  overflow-x: hidden;
  position: relative;
}

.sections {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  align-content: start;
  gap: 1px;

  .section {
    height: 59vw;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #000;
    position: relative;

    &.active::before {
      content: '播放中';
      position: absolute;
      background: rgba(0, 0, 0, 0.3);
      backdrop-filter: blur(3px);
      inset: 0;
      z-index: 12;
      color: #fff;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    img {
      display: block;
      max-width: 100%;
      max-height: 100%;
    }

    .section-title {
      color: #fff;
      position: absolute;
      bottom: 1vw;
      left: 1vw;
      z-index: 11;
      width: 100%;
      font-size: 3.2vw;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }

    .section-duration {
      color: #fff;
      position: absolute;
      font-size: 3vw;
      top: 1vw;
      right: 1vw;
    }
  }
}
.main {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
}
.swiper {
  top: 0;
  left: 0;
  width: 100%;
  flex: 1;
}
.video {
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0);
  border-bottom: 1px solid rgba(255, 255, 255);

  .title {
    color: #fff;
    position: absolute;
    bottom: 40px;
    padding: 5px;
    font-size: 15px;
    width: 100%;
    z-index: 999;
  }
}

.catelog-popup {
  height: 100%;
  width: 80%;
  padding: 10px;
  line-height: 1.5;
  font-size: 15px;
  .collection {
    margin-bottom: 15px;
  }
  .catelog {
    margin-top: 6px;
  }
  .collection-title {
    font-weight: bold;
  }
  .course {
    color: rgba(0, 0, 0, 0.8);
    line-height: 1.8;
    margin-top: 5px;
    word-break: break-all;

    &.active {
      color: #3c6bde;
    }

    .duration {
      color: #969799;
      font-size: 13px;
    }
  }
}
.icon {
  margin-right: 3px;
}

.btn {
  position: absolute;
  color: rgba(255, 255, 255, 0.6);
  z-index: 999;
  border: 1px solid rgba(255, 255, 255, 0.6);
  border-radius: 50px;
  width: 35px;
  height: 35px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.6);
  z-index: 9;
  right: 10px;
}

.btn-back {
  top: 10px;
}

.actions {
  right: 0;
  bottom: 0;
  position: absolute;
  z-index: 999;
  display: flex;
  align-items: center;
  height: 40px;

  .action-item {
    font-size: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    border: 1px solid #fff;
    margin-right: 5px;
    border-radius: 50px;
    padding: 5px 10px;

    &.active {
      color: #3266e6;
      border: 1px solid #3266e6;
    }
  }
}

.loading {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 0 !important;
  background: rgba(0, 0, 0, 0.6);
  z-index: 100;

  :deep(.van-loading__spinner) {
    color: #fff !important;
  }
}
</style>
